﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BbsbWebService.Tasks;
using System.Xml.Linq;
using System.Windows.Forms;
using System.IO;

namespace BbsbWebService.Repositories.Server
{
    public class ServerTaskRepository : ServerRepositoryBase<BaseTask>
    {
        Timer _timer; 

        #region RepositoryBase<BaseTask> Members

        public override void Initialise()
        {
            InitialiseTimer();
            
            if (File.Exists(AppSettings.SettingsFile.FullName))
            {
                XDocument doc = XDocument.Load(AppSettings.SettingsFile.FullName);

                foreach (var oot in doc.Descendants("BbsbWebService.Tasks.OneOffTask"))
                    AddTaskWithNextAlarmCheck(new OneOffTask(oot));

                foreach (var st in doc.Descendants("BbsbWebService.Tasks.ScheduledTask"))
                    AddTaskWithNextAlarmCheck(new ScheduledTask(st));

                foreach (var rt in doc.Descendants("BbsbWebService.Tasks.RecurringTask"))
                    AddTaskWithNextAlarmCheck(new RecurringTask(rt));

            }
        }

        public override void SaveItem(BaseTask task)
        {
            base.SaveItem(task);
            CheckTimer();
        }

        public override void RemoveItem(BaseTask task)
        {
            base.RemoveItem(task);
            CheckTimer();
        }

        public override XElement SaveRepository()
        {
            XElement element = new XElement("Tasks",
                from task in Items
                select task.GetAsXElement());

            return element;
        }

        #endregion

        private void AddTaskWithNextAlarmCheck(BaseTask task)
        {
            if (task.NextAlarm.HasValue)
            {
                Items.Add(task);
            }
        }

        private void InitialiseTimer()
        {
            _timer = new Timer
            {
                Enabled = false,
                Interval = 60000 // a minute
            };

            _timer.Tick += (o, s) =>
            {
                for (int i = 0; i< Items.Count; i++)
                {
                    var task = Items[i];
                    DateTime now = DateTime.Now;

                    if (task.NextAlarm.HasValue && task.NextAlarm.Value < now)
                    {
                        task.Execute();
                        if (task.NextAlarm == null)
                        {
                            Items.Remove(task);
                        }
                    }
                }
                CheckTimer();
            };
        }

        private void CheckTimer()
        {
            if (Items.Count > 0)
            {
                StartTimer();
            }
            else
            {
                StopTimer();
            }
        }

        private void StartTimer()
        {
            if (_timer != null)
                StopTimer();
            InitialiseTimer();
            _timer.Enabled = true;
            _timer.Start();
        }

        private void StopTimer()
        {
            // ensure timer is stopped
            _timer.Stop();
            _timer.Enabled = false;
            _timer = null;
        }
    }
}
